/*************************************************
Copyright © FJ Ltd. 2025 All rights reserved（版权所有）.
File name: 顺序表存储结构（数组）
Author： 赵留刚
Version: 1.0.0
Description: // 用于详细说明此程序文件完成的主要功能，与其他模块
             // 或函数的接口，输出值、取值范围、含义及参数间的控
             // 制、顺序、独立或依赖等关系
Others:      // 其它内容的说明
Log:         // 修改日志，包括修改内容，日期，修改人等
Date            Author          Version      Comment/Description
2025/03/19      赵留刚           1.0.0        代码初始规范化
*************************************************/

#include "Arrary_structure.h"
#include<stdlib.h>
#include<stdio.h>

/**
  ***********************************************************************
  * @brief   初始化动态数组
  * @param   DynamicArray *array： 动态数组指针
  * @param   size_t initialCapacity： 初始容量
  * @retval  1：初始化成功, -1：初始化失败
  * @note
  ***********************************************************************
  */
int initDynamicArray(DynamicArray *array, size_t initialCapacity)
{
    array->array = (int*)malloc(sizeof(int) * initialCapacity); //申请动态数据大小的内存空间

    if (array->array == NULL) //判断内存是否申请成功
    {
        printf("内存申请失败\n");//打印错误信息
        return -1;//内存未申请成功返回-1
    }

    array->capacity = initialCapacity;//初始化数组容量为initialCapacity
    array->length = 0;//初始化数组长度为0
    printf("数组初始化成功\n");
    return 1;
}

/**
  ***********************************************************************
  * @brief   释放动态数组内存
  * @param   DynamicArray *array： 动态数组指针
  * @retval  1：释放成功, -1：释放失败
  * @note
  ***********************************************************************
  */
int destroyDynamicArray(DynamicArray *array)
{
    if (array->array != NULL) //判断数组是否为空
    {
        free(array->array); //释放数组内存
        array->array = NULL; //将数组指针置为空
        array->capacity = 0; //将数组容量置默认值为0
        array->length = 0; //将数组长度置默认值为0
        return 1;//内存释放成功
    }
    else
    {
        printf("数组为空\n");//打印错误信息
        return -1;//内存释放失败
    }
}

/**
  ***********************************************************************
  * @brief   调整动态数组内存大小
  * @param   DynamicArray *array： 动态数组指针
  * @param   size_t newCapacity： 新的容量大小
  * @retval  1：调整成功, -1：调整失败
  * @note
  ***********************************************************************
  */
int resizeDynamicArray(DynamicArray *array, size_t newCapacity)
{
    array->array = (int*)realloc(array->array, sizeof(int) * newCapacity);

    if (array->array == NULL) //判断内存是否申请成功
    {
        printf("内存重新申请失败\n");//打印错误信息
        return -1;//内存重新调整失败
    }

    printf("动态调整数组内存大小成功\n");
    array->capacity = newCapacity;//将数组容量设置为newCapacity
    return 1;//内存调成成功
}

/**
  ***********************************************************************
  * @brief   获取动态数组长度（元素个数）
  * @param   DynamicArray *array
  * @retval  动态数组中元素个数
  * @note
  ***********************************************************************
  */
int getLength(const DynamicArray *array)
{
    return array->length; //返回数组长度
}

/**
  ***********************************************************************
  * @brief   在指定位置插入新元素
  * @param   DynamicArray *array： 动态数组指针
  * @param   size_t index： 插入位置索引
  * @param   int element： 插入元素
  * @retval  1：插入成功, -1：插入失败
  * @note：数组是顺序紧密连续存储，中间不能有空位，
  ***********************************************************************
  */
int insertAt(DynamicArray *array, size_t index, int element)
{
    /* 第1种情况、判断插入位置的索引是否合法，需要插入元素的位置在数组长度范围内，即数组是否越界 */
    if (index < 0 || index > array->length)
    {
        printf("index索引不合法，插入失败\n");
        return -1;
    }

    /* 第2种情况、判断当前数组是否已满，若满则扩展数组 */
    if (array->length >= array->capacity)
    {
        // resizeDynamicArray(array, array->capacity * 2);//在原来的基础上扩容2倍
        // resizeDynamicArray(array->array, (array->capacity) << 1); //在原来的基础上扩容2倍，左移1位相当于乘以2，右移1位相当于除以2
        resizeDynamicArray(array, array->capacity + array->capacity >> 1); //扩容1.5倍
    }

    /* 3、将元素后移，为新元素腾出位置 */
    for (size_t i = array->length; i > index; i--)
    {
        array->array[i] = array->array[i - 1];//将数组中索引为index及之后的数据依次往后移动1个int类型的大小
    }

    /* 4、插入新元素 */
    array->array[index] = element;//在指定位置index处插入新元素
    array->length++;//更新数组长度
    return 1;//在数组指定位置插入元素成功
}

/**
  ***********************************************************************
  * @brief   在开头插入新元素
  * @param   DynamicArray *array： 动态数组指针
  * @param   int element： 插入的元素
  * @retval  1：插入成功, -1：插入失败
  * @note
  ***********************************************************************
  */
int insertBegin(DynamicArray *array, int element)
{
    /* 1、 检查数组容量，容量用完则重新申请 */
    if (array->length == array->capacity)
    {
        resizeDynamicArray(array, array->capacity + array->capacity >> 1);
    }

    /* 2、 将数组中元素后移，为插入的新元素腾出位置 */
    for (int i = array->length; i > 0; i--)
    {
        array->array[i] = array->array[i - 1];
    }

    /* 3、 在数字开头插入新的元素 */
    array->array[0] = element;//在数组开头插入element元素
    array->length++;//更新数组长度
    return 1;//在数组开头位置插入元素成功
}

/**
  ***********************************************************************
  * @brief   在末尾插入新元素
  * @param   DynamicArray *array： 动态数组指针
  * @param   int element： 插入的元素
  * @retval  1：插入成功, -1：插入失败
  * @note：
  ***********************************************************************
  */
int insertEnd(DynamicArray *array, int element)
{
    /* 1、 检查数组容量，使用完时重新申请 */
    if (array->length == array->capacity)
    {
        resizeDynamicArray(array, array->capacity + ((array->capacity) >> 1));//数组容量扩大为原来的1.5倍
    }

    /* 2、 在数组末尾插入新的元素 */
    array->array[array->length] = element;
    return 1;//在数组末尾插入元素成功
}

/**
  ***********************************************************************
  * @brief   删除指定位置的元素并返回被删除的元素
  * @param   DynamicArray *array： 动态数组指针
  * @param   size_t index： 删除元素的位置索引
  * @retval  -1：删除失败，其他值是被删除的元素
  * @note
  ***********************************************************************
  */
int deleteAt(DynamicArray *array, size_t index)
{
    /* 1、 判断删除元素的索引是否越界 */
    if (index < 0 || index >= array->length)
    {
        printf("删除元素的索引越界，元素删除失败\n");
        return -1;
    }

    /* 2、 需要删除的元素 */
    int deleteData = array->array[index];

    /* 3、 将删除元素后面的元素依次向前移动1位 */
    for (size_t i = index; i < array->length - 1; i++)
    {
        array->array[i] = array->array[i + 1];
    }

    array->length--;
    return deleteData;
}

/**
  ***********************************************************************
  * @brief   删除头部的元素并返回被删除的元素
  * @param   DynamicArray *array： 动态数组指针
  * @retval  -1：删除失败，其他值是被删除的元素
  * @note
  ***********************************************************************
  */
int deleteBegin(DynamicArray *array)
{
    /* 判断数组是否为空 */
    if (array->length == 0)
    {
        printf("数组为空，无法删除元素\n");
        return -1;
    }

    /* 1、 需要删除的元素 */
    int deleteData = array->array[0];

    /* 2、 将删除元素后面的元素向前移动1位 */
    for (size_t i = 0; i < array->length; i++)
    {
        array->array[i] = array->array[i + 1];
    }

    array->length--;
    return deleteData;
}

/**
  ***********************************************************************
  * @brief   删除末尾的元素并返回被删除的元素
  * @param   DynamicArray *array： 动态数组指针
  * @retval  -1：删除失败，其他值是被删除的元素
  * @note
  ***********************************************************************
  */
int deleteEnd(DynamicArray *array)
{
    /* 判断数组是否为空 */
    if (array->length == 0)
    {
        printf("数组为空，无法删除元素\n");
        return -1;
    }

    /* 1、 需要删除的元素 */
    int deleteData = array->array[array->length - 1];
    /* 2、 删除数组末尾元素 */
    array->length--;
    return deleteData;
}

/**
  ***********************************************************************
  * @brief   遍历所有的元素
  * @param   DynamicArray *array： 动态数组指针
  * @retval  None
  * @note
  ***********************************************************************
  */
void print_all_element(DynamicArray *array)
{
    for (int i = 0; i < array->length; i++)
    {
        printf("%d ", array->array[i]);
    }

    printf("\n");
}